package com.zenglx.multilanguage.metadata;

import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.SqlCondition;
import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;
import com.baomidou.mybatisplus.core.metadata.TableInfo;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;
import lombok.Getter;
import lombok.Setter;

import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.joining;


@Getter
@Setter
public class ZlxTableInfo extends TableInfo {
    private String condition = SqlCondition.EQUAL;
    /**
     * 多语言字段
     */
    private Set<TableFieldInfo> multiLanguageColumns = new HashSet<>();

    /**
     * 实体类 => 主键信息
     */
    private Set<TableFieldInfo> entityClassPkColumns = new HashSet<>();

    /**
     * 实体类 => 全部列
     */
    private Set<TableFieldInfo> entityClassColumns = new HashSet<>();

    /**
     * 是否多语言
     */
    private boolean multiLanguage;

    public ZlxTableInfo(Class<?> entityType) {
        super(entityType);
    }


    public List<String> multiLanguageColumns() {
        return multiLanguageColumns.stream()
                .map(TableFieldInfo::getColumn).collect(Collectors.toList());
    }


    /**
     * 获取所有的查询的 sql 片段
     *
     * @param ignoreLogicDelFiled 是否过滤掉逻辑删除字段
     * @param withId              是否包含 id 项
     * @param prefix              前缀
     * @return sql 脚本片段
     */
    @Override
    public String getAllSqlWhere(boolean ignoreLogicDelFiled, boolean withId, final String prefix) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        String filedSqlScript = super.getFieldList().stream()
                .filter(i -> {
                    if (ignoreLogicDelFiled) {
                        return !(isWithLogicDelete() && i.isLogicDelete());
                    }
                    return true;
                })
                .map(i -> getSqlWhere(newPrefix,i)).filter(Objects::nonNull).collect(joining(NEWLINE));
        if (!withId || StringUtils.isBlank(super.getKeyProperty())) {
            return filedSqlScript;
        }
        String newKeyProperty = newPrefix + super.getKeyProperty();
        String keySqlScript = super.getKeyColumn() + EQUALS + SqlScriptUtils.safeParam(newKeyProperty);
        return SqlScriptUtils.convertIf(keySqlScript, String.format("%s != null", newKeyProperty), false)
                + NEWLINE + filedSqlScript;
    }

    private String convertIfProperty(String prefix, String property) {
        return StringUtils.isNotBlank(prefix) ? prefix.substring(0, prefix.length() - 1) + "['" + property + "']" : property;
    }

    /**
     * 获取 查询的 sql 片段
     *
     * @param prefix 前缀
     * @return sql 脚本片段
     */
    public String getSqlWhere(final String prefix,TableFieldInfo tableFieldInfo) {
        final String newPrefix = prefix == null ? EMPTY : prefix;
        // 默认:  AND column=#{prefix + el}
        String sqlScript = " AND " + String.format(condition, tableFieldInfo.getColumn(), newPrefix + tableFieldInfo.getEl());
        if(this.getMultiLanguageColumns().contains(tableFieldInfo)) {
            sqlScript = " AND " + String.format(condition, "t."+tableFieldInfo.getColumn(), newPrefix + tableFieldInfo.getEl());
        }
        // 查询的时候只判非空
        return convertIf(sqlScript, convertIfProperty(newPrefix, convertIfProperty(newPrefix, tableFieldInfo.getProperty())), tableFieldInfo);
    }

    /**
     * 转换成 if 标签的脚本片段
     *
     * @param sqlScript     sql 脚本片段
     * @param property      字段名
     * @param tableFieldInfo 验证策略
     * @return if 脚本片段
     */
    private String convertIf(final String sqlScript, final String property, TableFieldInfo tableFieldInfo) {
        if (tableFieldInfo.getWhereStrategy() == FieldStrategy.NEVER) {
            return null;
        }
        if (tableFieldInfo.isPrimitive() || tableFieldInfo.getWhereStrategy() == FieldStrategy.IGNORED) {
            return sqlScript;
        }
        if (tableFieldInfo.getWhereStrategy() == FieldStrategy.NOT_EMPTY && tableFieldInfo.isCharSequence()) {
            return SqlScriptUtils.convertIf(sqlScript, String.format("%s != null and %s != ''", property, property),
                    false);
        }
        return SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", property), false);
    }

}
